from subprocess import run, PIPE, DEVNULL, Popen

from .service import ServiceDirection, ServiceState
from .git_service import GitBasedService


class DockerComposeService(GitBasedService):
    def __init__(self, name, directory):
        super().__init__(directory)
        self._name = name
        self._directory = directory
        self._state = ServiceState.UNKNOWN
        self._direction = ServiceDirection.NONE

    def _compose_command_line(self, args):
        return ['docker-compose',
                '-f', '%s/docker-compose.yml' % self._directory] + args

    def _run_compose_fg(self, args):
        return run(self._compose_command_line(args),
                   stdout=PIPE,
                   stderr=PIPE)

    def _run_compose_bg(self, args):
        Popen(self._compose_command_line(args), stdout=DEVNULL, stderr=DEVNULL)

    def update_state(self):
        proc = self._run_compose_fg(['ps'])

        if proc.returncode != 0:
            self._state = ServiceState.UNKNOWN
            return

        words = ' '.join(proc.stdout.decode('utf-8').split('\n')[2:]).split()
        has_running = 'Up' in words
        has_stopped = 'Exit' in words

        if self._direction == ServiceDirection.UP:
            self._state = (ServiceState.STARTING
                           if has_stopped
                           else ServiceState.UP)
        elif self._direction == ServiceDirection.DOWN:
            self._state = (ServiceState.STOPPING
                           if has_running
                           else ServiceState.DOWN)
        elif self._direction == ServiceDirection.NONE:
            if has_running:
                if has_stopped:
                    self._state = ServiceState.UNKNOWN
                else:
                    self._state = ServiceState.UP
            else:
                if has_stopped:
                    self._state = ServiceState.DOWN
                else:
                    self._state = ServiceState.DOWN

    def start(self):
        self._direction = ServiceDirection.UP
        self._state = ServiceState.STARTING
        self._run_compose_bg(['up'])

    def stop(self):
        self._direction = ServiceDirection.DOWN
        self._state = ServiceState.STOPPING
        self._run_compose_bg(['down'])
